using CollabApp.Domain.Services.Game;
using CollabApp.Application.Interfaces;
using Microsoft.Extensions.Logging;
using System.Text.Json;

namespace CollabApp.Application.Services.Game;

/// <summary>
/// 特殊事件服务实现
/// 负责处理游戏中的特殊事件，包括重力反转、时间加速等
/// </summary>
public class SpecialEventService : ISpecialEventService
{
    private readonly IRedisService _redisService;
    private readonly ILogger<SpecialEventService> _logger;
    private readonly Random _random;
    
    /// <summary>
    /// 特殊事件触发概率（10%）
    /// </summary>
    private const double EVENT_TRIGGER_PROBABILITY = 0.1;
    
    /// <summary>
    /// Redis键模板
    /// </summary>
    private static class RedisKeys
    {
        public const string GameSpecialEvents = "game:{0}:special_events";
        public const string EventTriggered = "game:{0}:event_triggered";
    }

    public SpecialEventService(
        IRedisService redisService,
        ILogger<SpecialEventService> logger)
    {
        _redisService = redisService;
        _logger = logger;
        _random = new Random();
    }

    /// <summary>
    /// 检查是否应该触发特殊事件
    /// </summary>
    public async Task<bool> ShouldTriggerSpecialEventAsync(Guid gameId)
    {
        try
        {
            // 检查是否已经触发过特殊事件
            var eventTriggeredKey = string.Format(RedisKeys.EventTriggered, gameId);
            var hasTriggered = await _redisService.ExistsAsync(eventTriggeredKey);
            
            if (hasTriggered)
            {
                return false; // 每局游戏只能触发一次
            }

            // 10%概率触发特殊事件
            var shouldTrigger = _random.NextDouble() < EVENT_TRIGGER_PROBABILITY;
            
            _logger.LogDebug("特殊事件触发检查 - GameId: {GameId}, ShouldTrigger: {ShouldTrigger}", 
                gameId, shouldTrigger);
            
            return shouldTrigger;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "检查特殊事件触发条件失败 - GameId: {GameId}", gameId);
            return false;
        }
    }

    /// <summary>
    /// 触发随机特殊事件
    /// </summary>
    public async Task<SpecialEventResult> TriggerRandomEventAsync(Guid gameId)
    {
        try
        {
            // 检查是否已经触发过
            var eventTriggeredKey = string.Format(RedisKeys.EventTriggered, gameId);
            var hasTriggered = await _redisService.ExistsAsync(eventTriggeredKey);
            
            if (hasTriggered)
            {
                return new SpecialEventResult
                {
                    Success = false,
                    Errors = { "该游戏已经触发过特殊事件" }
                };
            }

            // 随机选择事件类型
            var eventTypes = Enum.GetValues<SpecialEventType>();
            var selectedType = eventTypes[_random.Next(eventTypes.Length)];
            
            // 触发选中的事件
            var result = await TriggerEventAsync(gameId, selectedType);
            
            // 标记已触发
            if (result.Success)
            {
                await _redisService.SetStringAsync(eventTriggeredKey, "true", TimeSpan.FromHours(1));
                
                _logger.LogInformation("随机特殊事件触发成功 - GameId: {GameId}, EventType: {EventType}, EventId: {EventId}", 
                    gameId, selectedType, result.EventId);
            }
            
            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "触发随机特殊事件失败 - GameId: {GameId}", gameId);
            return new SpecialEventResult
            {
                Success = false,
                Errors = { "触发特殊事件时发生内部错误" }
            };
        }
    }

    /// <summary>
    /// 触发指定特殊事件
    /// </summary>
    public async Task<SpecialEventResult> TriggerEventAsync(Guid gameId, SpecialEventType eventType)
    {
        try
        {
            var eventId = $"event_{gameId}_{DateTime.UtcNow.Ticks}";
            var startTime = DateTime.UtcNow;
            var eventConfig = GetEventConfiguration(eventType);
            var endTime = startTime.Add(eventConfig.Duration);
            
            var eventData = new ActiveSpecialEvent
            {
                EventId = eventId,
                EventType = eventType,
                EventName = eventConfig.Name,
                StartTime = startTime,
                RemainingSeconds = (int)eventConfig.Duration.TotalSeconds,
                IsActive = true,
                Progress = 0f,
                Parameters = eventConfig.Parameters
            };

            // 保存到Redis
            var eventsKey = string.Format(RedisKeys.GameSpecialEvents, gameId);
            var eventJson = JsonSerializer.Serialize(eventData);
            await _redisService.SetHashAsync(eventsKey, eventId, eventJson);
            await _redisService.ExpireAsync(eventsKey, TimeSpan.FromHours(1));

            var result = new SpecialEventResult
            {
                Success = true,
                EventId = eventId,
                EventType = eventType,
                EventName = eventConfig.Name,
                Description = eventConfig.Description,
                StartTime = startTime,
                Duration = eventConfig.Duration,
                EndTime = endTime,
                AffectedPlayerIds = new List<Guid>(), // 所有玩家都受影响
                EventParameters = eventConfig.Parameters,
                Messages = { $"特殊事件 '{eventConfig.Name}' 开始！", eventConfig.Description }
            };

            _logger.LogInformation("特殊事件触发 - GameId: {GameId}, EventType: {EventType}, EventId: {EventId}, Duration: {Duration}秒", 
                gameId, eventType, eventId, eventConfig.Duration.TotalSeconds);

            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "触发特殊事件失败 - GameId: {GameId}, EventType: {EventType}", gameId, eventType);
            return new SpecialEventResult
            {
                Success = false,
                EventType = eventType,
                Errors = { "触发特殊事件时发生内部错误" }
            };
        }
    }

    /// <summary>
    /// 获取当前活跃的特殊事件
    /// </summary>
    public async Task<List<ActiveSpecialEvent>> GetActiveEventsAsync(Guid gameId)
    {
        try
        {
            var eventsKey = string.Format(RedisKeys.GameSpecialEvents, gameId);
            var eventData = await _redisService.GetHashAllAsync(eventsKey);
            
            var activeEvents = new List<ActiveSpecialEvent>();
            var currentTime = DateTime.UtcNow;
            
            foreach (var kvp in eventData)
            {
                try
                {
                    var eventObj = JsonSerializer.Deserialize<ActiveSpecialEvent>(kvp.Value);
                    if (eventObj != null)
                    {
                        var eventConfig = GetEventConfiguration(eventObj.EventType);
                        var elapsed = currentTime - eventObj.StartTime;
                        var remaining = eventConfig.Duration - elapsed;
                        
                        if (remaining.TotalSeconds > 0)
                        {
                            eventObj.RemainingSeconds = (int)remaining.TotalSeconds;
                            eventObj.Progress = (float)(elapsed.TotalSeconds / eventConfig.Duration.TotalSeconds);
                            eventObj.IsActive = true;
                            activeEvents.Add(eventObj);
                        }
                        else
                        {
                            eventObj.IsActive = false;
                        }
                    }
                }
                catch (JsonException ex)
                {
                    _logger.LogWarning(ex, "解析特殊事件数据失败 - GameId: {GameId}, EventId: {EventId}", 
                        gameId, kvp.Key);
                }
            }
            
            return activeEvents;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取活跃特殊事件失败 - GameId: {GameId}", gameId);
            return new List<ActiveSpecialEvent>();
        }
    }

    /// <summary>
    /// 更新特殊事件状态
    /// </summary>
    public async Task<EventUpdateResult> UpdateEventStatusAsync(Guid gameId)
    {
        try
        {
            var eventsKey = string.Format(RedisKeys.GameSpecialEvents, gameId);
            var eventData = await _redisService.GetHashAllAsync(eventsKey);
            
            var result = new EventUpdateResult();
            var currentTime = DateTime.UtcNow;
            
            foreach (var kvp in eventData)
            {
                try
                {
                    var eventObj = JsonSerializer.Deserialize<ActiveSpecialEvent>(kvp.Value);
                    if (eventObj != null)
                    {
                        var eventConfig = GetEventConfiguration(eventObj.EventType);
                        var elapsed = currentTime - eventObj.StartTime;
                        
                        if (elapsed >= eventConfig.Duration)
                        {
                            // 事件已完成
                            result.CompletedEvents.Add(eventObj.EventId);
                            await _redisService.DeleteHashAsync(eventsKey, kvp.Key);
                            
                            _logger.LogInformation("特殊事件完成 - GameId: {GameId}, EventType: {EventType}, EventId: {EventId}", 
                                gameId, eventObj.EventType, eventObj.EventId);
                        }
                        else
                        {
                            // 事件仍在进行，更新进度
                            eventObj.RemainingSeconds = (int)(eventConfig.Duration - elapsed).TotalSeconds;
                            eventObj.Progress = (float)(elapsed.TotalSeconds / eventConfig.Duration.TotalSeconds);
                            eventObj.IsActive = true;
                            
                            result.ActiveEvents.Add(eventObj);
                            
                            // 更新Redis中的数据
                            var updatedEventJson = JsonSerializer.Serialize(eventObj);
                            await _redisService.SetHashAsync(eventsKey, kvp.Key, updatedEventJson);
                        }
                    }
                }
                catch (JsonException ex)
                {
                    _logger.LogWarning(ex, "更新特殊事件状态时解析数据失败 - GameId: {GameId}, EventId: {EventId}", 
                        gameId, kvp.Key);
                }
            }
            
            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "更新特殊事件状态失败 - GameId: {GameId}", gameId);
            return new EventUpdateResult();
        }
    }

    /// <summary>
    /// 结束指定特殊事件
    /// </summary>
    public async Task<bool> EndEventAsync(Guid gameId, string eventId)
    {
        try
        {
            var eventsKey = string.Format(RedisKeys.GameSpecialEvents, gameId);
            var success = await _redisService.DeleteHashAsync(eventsKey, eventId);
            
            if (success)
            {
                _logger.LogInformation("特殊事件手动结束 - GameId: {GameId}, EventId: {EventId}", gameId, eventId);
            }
            
            return success;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "结束特殊事件失败 - GameId: {GameId}, EventId: {EventId}", gameId, eventId);
            return false;
        }
    }

    /// <summary>
    /// 获取事件配置
    /// </summary>
    private EventConfiguration GetEventConfiguration(SpecialEventType eventType)
    {
        return eventType switch
        {
            SpecialEventType.GravityReverse => new EventConfiguration
            {
                Name = "重力反转",
                Description = "所有玩家移动方向反转（按W向下移动）",
                Duration = TimeSpan.FromSeconds(20),
                Parameters = new Dictionary<string, object>
                {
                    ["reverseControls"] = true,
                    ["visualEffect"] = "screen_rotation",
                    ["intensity"] = 1.0f
                }
            },
            SpecialEventType.TimeAcceleration => new EventConfiguration
            {
                Name = "时间加速",
                Description = "所有玩家移动速度翻倍，但画线更难控制",
                Duration = TimeSpan.FromSeconds(15),
                Parameters = new Dictionary<string, object>
                {
                    ["speedMultiplier"] = 2.0f,
                    ["controlDifficulty"] = 1.5f,
                    ["visualEffect"] = "time_warp",
                    ["trailWidth"] = 3.0f
                }
            },
            SpecialEventType.PowerUpRain => new EventConfiguration
            {
                Name = "道具雨",
                Description = "地图上同时刷新8-12个随机道具",
                Duration = TimeSpan.FromSeconds(1), // 瞬间事件
                Parameters = new Dictionary<string, object>
                {
                    ["powerUpCount"] = _random.Next(8, 13),
                    ["spawnAnimation"] = "falling_from_sky",
                    ["spawnDuration"] = 2.0f
                }
            },
            SpecialEventType.TerritoryQuake => new EventConfiguration
            {
                Name = "领地震动",
                Description = "所有玩家的领地边界随机波动，面积±5%变化",
                Duration = TimeSpan.FromSeconds(10),
                Parameters = new Dictionary<string, object>
                {
                    ["areaVariation"] = 0.05f,
                    ["shakeDuration"] = 0.2f,
                    ["shakeIntensity"] = 5.0f,
                    ["visualEffect"] = "territory_shake"
                }
            },
            SpecialEventType.InvisibilityMode => new EventConfiguration
            {
                Name = "透明模式",
                Description = "所有玩家轨迹变为半透明，更难被发现",
                Duration = TimeSpan.FromSeconds(30),
                Parameters = new Dictionary<string, object>
                {
                    ["trailOpacity"] = 0.4f,
                    ["playerOpacity"] = 0.7f,
                    ["visualEffect"] = "invisibility"
                }
            },
            _ => new EventConfiguration
            {
                Name = "未知事件",
                Description = "未知的特殊事件",
                Duration = TimeSpan.FromSeconds(10),
                Parameters = new Dictionary<string, object>()
            }
        };
    }

    /// <summary>
    /// 事件配置类
    /// </summary>
    private class EventConfiguration
    {
        public string Name { get; set; } = string.Empty;
        public string Description { get; set; } = string.Empty;
        public TimeSpan Duration { get; set; }
        public Dictionary<string, object> Parameters { get; set; } = new();
    }
}
